package com.tsinghuabigdata.edu.ddmath.module.ddwork.camera;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.ImageFormat;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.YuvImage;
import android.hardware.Camera;
import android.os.AsyncTask;

import com.tsinghuabigdata.edu.ddmath.constant.AppConst;
import com.tsinghuabigdata.edu.ddmath.module.ddwork.DDWorkManager;
import com.tsinghuabigdata.edu.ddmath.opencv.OpenCVHelper;
import com.tsinghuabigdata.edu.ddmath.util.AppLog;

import java.io.ByteArrayOutputStream;

/**
 * 实时预览处理
 */
public class CameraPreviewCallBack implements Camera.PreviewCallback {

    private DetechAynscTask mDetechAynscTask;

    private Rect mFixRect;     //定位识别框
    private Rect mCropRect;     //图片裁剪框
    private DetectListener mDetectListener;

    private boolean runStatus = false;

    private Context mContext;
    private int mCameraPreviewWidth;            //相机预览大小
    private int mCamreaPriviewHeight;

    public CameraPreviewCallBack(Context c){
        mContext = c;
    }

    @Override
    public void onPreviewFrame(byte[] data, Camera camera) {

        if( runStatus )
            return;

        if( null != mDetechAynscTask ){
            if( !mDetechAynscTask.isFinish() )
                return;                 //没有结束识别
            else
                mDetechAynscTask.cancel( false );
        }

        mDetechAynscTask = new DetechAynscTask( data, camera );
        mDetechAynscTask.execute();
    }

    public void setData( Rect croprect, Rect fixrect, DetectListener listener, int viewWidth, int viewHaight ){
        mCropRect = croprect;
        mFixRect = fixrect;
        mDetectListener = listener;

        mCameraPreviewWidth = viewWidth;
        mCamreaPriviewHeight = viewHaight;
    }

    public void setRunStatus( boolean status ){
        runStatus = status;
    }

    public void stopDetechAynscTask(){
        if( null != mDetechAynscTask && !mDetechAynscTask.isFinish() ){
            mDetechAynscTask.cancel( true );
        }
    }

    private int index = 0;
    class DetechAynscTask extends AsyncTask<Void,Void,Boolean> {

        private byte[] mData;
        private Camera mCamera;

        private boolean bFinish;

        private long time;

        public DetechAynscTask(byte[] data, Camera camera) {
            mData = data;
            mCamera = camera;
            bFinish = false;
        }

        public boolean isFinish() {
            return bFinish;
        }

        @Override
        protected Boolean doInBackground(Void... params) {

            AppLog.i(" DetechAynscTask exec start ");

            bFinish = false;
            time = System.currentTimeMillis();

            if (mCamera == null) return false;

            Camera.Size size = mCamera.getParameters().getPreviewSize(); //获取预览大小
            Camera.Size psize = mCamera.getParameters().getPictureSize();


            final int w = size.width;  //宽度
            final int h = size.height;
            AppLog.i(" DetechAynscTask PreviewSize w = " + w + ",,, h = " + h + ",,, PictureSize w = " + psize.width + ",, h = " + psize.height );
            final YuvImage image = new YuvImage(mData, ImageFormat.NV21, w, h, null);
            ByteArrayOutputStream os = new ByteArrayOutputStream(mData.length);
            if (!image.compressToJpeg(new Rect(0, 0, w, h), 100, os)) {
                return false;
            }
            byte[] bytes = os.toByteArray();
            Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);

            if( mFixRect!=null && mDetectListener!=null&& mCropRect!=null ){

                // 默认取camera0 的角度
                int degree[] = new int[1];
                mDetectListener.cameraRorate( degree );
                if( degree[0] != 0 ){
                    Matrix matrix = new Matrix();
                    //int width = bmp.getWidth(), height = bmp.getHeight();
                    if( bitmap.getWidth() > 2000 || bitmap.getHeight() > 2000 ){
                        matrix.postScale( 0.5f, 0.5f );
                    }
                    matrix.postRotate( degree[0] );
                    Bitmap bmp = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);

                    bitmap.recycle();
                    bitmap = bmp;
                }

                //AppLog.i(" DetechAynscTask exec mRect.top = " + mFixRect.top + ",,, left = " + mFixRect.left + ",,, width = " + mFixRect.width() + ",,, height = " + mFixRect.height()  );

                AppLog.i(" DetechAynscTask mCameraPreviewWidth = " + mCameraPreviewWidth + ",,, mCamreaPriviewHeight = " + mCamreaPriviewHeight);

                //从 bitmap 里面 按比例裁剪出 目标图片
                float w_rate = bitmap.getWidth()  * 1.0f / mCameraPreviewWidth;       //预览与成像的比例关系
                float h_rate = bitmap.getHeight() * 1.0f / mCamreaPriviewHeight;

                int left    = (int)(mCropRect.left * w_rate);
                int top     = (int)(mCropRect.top  * h_rate);
                int right   = (int)(mCropRect.right * w_rate);
                int bottom  = (int)(mCropRect.bottom  * h_rate);

                AppLog.i(" DetechAynscTask w_rate = " + w_rate + ",,, h_rate = " + h_rate );

                //对 mFixRect 进行比例变换
                int dw = (int)(mFixRect.width() * w_rate);
                int dh = (int)(mFixRect.height() * h_rate);

                Rect dstFixRect = new Rect();
                dstFixRect.left = (int)(mFixRect.left * w_rate);
                dstFixRect.top  = (int)(mFixRect.top * h_rate);
                dstFixRect.right= dstFixRect.left + dw;
                dstFixRect.bottom= dstFixRect.top + dh;

                AppLog.i(" DetechAynscTask sss bitmap left = " + left + ",,, top = " + top + ",,, width = " + (right-left) + ",,,height = " + (bottom-top) );

                Bitmap dstBitmap = Bitmap.createBitmap(bitmap, left, top, right-left, bottom-top );
                bitmap.recycle();
                bitmap = dstBitmap;

                //BitmapUtils.saveImage( DDWorkManager.getImagePath() + String.valueOf(index++) + AppConst.IMAGE_SUFFIX_NAME, bitmap );

                AppLog.i(" DetechAynscTask sss bitmap left = " + left + ",,, top = " + top + ",,, width = " + (right-left) + ",,,height = " + (bottom-top) );

                int ret = OpenCVHelper.detectBitmap( bitmap, dstFixRect.left*1000/bitmap.getWidth(), dstFixRect.top*1000/bitmap.getHeight(), dstFixRect.width()*1000/bitmap.getWidth(), dstFixRect.height()*1000/bitmap.getHeight() );
                mDetectListener.detectResult( ret );
                AppLog.i(" DetechAynscTask exec ret = " + ret );

                AppLog.i(" DetechAynscTask exec dstFixRect left = " + dstFixRect.left + ",,, top = " + dstFixRect.top + ",,, width = " + dstFixRect.width() + ",,, height = " + dstFixRect.height() );

                if( (ret & 0x7) == 7 ){

                    String imagepath = DDWorkManager.getImagePath() + System.currentTimeMillis()+ AppConst.IMAGE_SUFFIX_NAME;
                    boolean success = OpenCVHelper.getDetectImage( imagepath );
                    AppLog.i(" DetechAynscTask exec success = " + success + ",,, imagepath = " + imagepath );
                    if( success ){
                        mDetectListener.detectFile( imagepath );
                        bitmap.recycle();
                        return true;
                    }
                }
            }
            bitmap.recycle();
            return false;
        }

        @Override
        protected void onPostExecute(Boolean result) {
            runStatus = result;
            bFinish = true;
            AppLog.i(" DetechAynscTask exec result = " + result + ",,, time = " + (System.currentTimeMillis() - time));
        }
    }
}
